package com.uatair.common.mqtt.uploader;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.uatair.common.mqtt.domain.DroneResponse;
import com.uatair.common.mqtt.domain.dto.ApiUploadResponse;
import com.uatair.common.mqtt.domain.task.RecodeTask;
import com.uatair.common.mqtt.domain.task.SortieTask;
import com.uatair.common.mqtt.domain.task.TaskDTO;
import com.uatair.common.mqtt.domain.task.UavTask;
import com.uatair.common.mqtt.util.AESUtil;
import com.uatair.common.mqtt.util.UAesUtil;
import com.uatair.common.utils.StringUtils;
import com.uatair.common.utils.http.HttpUtils;
import com.uatair.common.utils.ip.AddressUtils;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONArray;
import org.json.JSONObject;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Slf4j
public class HuBeiTaskUploader {

    private static final String account = "szlianhefeiji";
    private static final String password = "Szlianhefeiji@123";
    private static final String url = "http://223.75.53.178:6789";

    public static void main(String[] args) throws Exception {
//        sendAreaMessage();
//        sendLocationMessage();
//        sendTrackMessage();
//        getHuBeiTaskDetail("1939580129050669056");
    }

    /**
     * 作业信息推送
     *
     * @throws Exception
     */
    public RecodeTask sendAreaMessage(SortieTask sortieTask){
        if (!StringUtils.isEmpty(sortieTask.getGeoJson())) {
            JSONArray jsonArray = new JSONArray();
            JSONObject json = new JSONObject();
            json.put("account", account);
            json.put("password", password);
            json.put("terminalNumber", "612737193106"/*agSortie.getSn()*/);
            json.put("toolType", "15");//15植保无人机
            json.put("jobType", "5");//5无人机植保
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
            SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//            Date endDate = sdf2.parse(sortieTask.getEndTime());
            json.put("jobDateTime", sdf1.format(sortieTask.getEndTime()));
            json.put("jobBeginDateTime", sdf2.format(sortieTask.getStartTime()));
            json.put("jobEndDateTime", sdf2.format(sortieTask.getEndTime()));
            json.put("jobTimes", (int) (sortieTask.getFlightTime() / 1000 / 60));//作业时长 分
            List<double[]> doubles = parseGeoJsonCoordinates(sortieTask.getGeoJson());
            if (!doubles.isEmpty()) {
                json.put("longitude", doubles.get(0)[0]);
                json.put("latitude", doubles.get(0)[1]);
                json.put("jobWidth", sortieTask.getLineSpacing());//宽幅
                DecimalFormat df = new DecimalFormat("0.00");
                json.put("jobArea", df.format(sortieTask.getSize()*0.0015));//面积
                json.put("jobAvgDepth", "0");//深度
                json.put("jobPassRate", "1");//合格率
                json.put("jobQualifiedArea", df.format(sortieTask.getSize()*0.0015));//合格亩数
                json.put("jobCoordinateGroup", convertToJsonString(doubles));
                json.put("auditFlag", "1");
                if (StringUtils.isNotEmpty(sortieTask.getPositionInfo())) {
                    Map<String, String> map = AddressUtils.parseChineseAddress(sortieTask.getPositionInfo());
                    json.put("province", map.getOrDefault("province", "辽宁省"));
                    json.put("city", map.getOrDefault("city", "朝阳市"));
                    json.put("country", map.getOrDefault("country", "朝阳县"));
                    json.put("town", map.getOrDefault("town", "根德营子乡"));
                    json.put("address", sortieTask.getPositionInfo()==null?"辽宁省朝阳市朝阳县根德营子乡":sortieTask.getPositionInfo());
                }
                json.put("jobAvgfertilizer ", sortieTask.getDosage());//施肥量
                jsonArray.put(json);
                System.out.println("request:" + jsonArray);
                String s = HttpUtils.sendHttpPost(url + "/agri-api/job/areaMessage", jsonArray.toString());
                System.out.println("result:" + s);
                ApiUploadResponse apiUploadResponse = new ApiUploadResponse("", s, url + "/agri-api/job/areaMessage", 200);
                return ZhiBaoYunTaskUploader.getRecode(apiUploadResponse, new JSONObject().put("data",jsonArray), "作业信息推送");
                /*return new RecodeTask(null,null,url + "/agri-api/job/areaMessage",jsonArray.toString(),null,s,200,
                        new Date(),"0","0","作业信息推送");*/
            }
        }
        return null;
    }

    /**
     * 位置信息推送 每分钟推一次
     *
     * @throws Exception
     */
    public RecodeTask sendLocationMessage(DroneResponse droneResponse) {
        JSONArray jsonArray = new JSONArray();
        JSONObject json = new JSONObject();
        json.put("account", account);
        json.put("password", password);
        if (droneResponse.getOsd()!=null) {
            if(droneResponse.getOsd().getLongitude()!=0) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                json.put("terminalNumber", "612737193106"/*droneResponse.getDroneId()*/);
                json.put("longitude", droneResponse.getOsd().getLongitude()/*"120.5651148"droneResponse.getOsd().getLongitude()*/);
                json.put("latitude", droneResponse.getOsd().getLatitude()/*"41.1542392"droneResponse.getOsd().getLatitude()*/);
                json.put("positionDateTime", sdf.format(new Date(droneResponse.getOsd().getTimestamp())));/*sdf.format(new Date()))new Date(droneResponse.getOsd().getTimestamp())*/
                json.put("positionType", 10);
                json.put("jobStatus", 1);
                json.put("startStatus", droneResponse.getOsd().getFlying()/*1droneResponse.getOsd().getFlying()*/);
                json.put("jobType", 0);
                json.put("jobIsPass", 0);
                json.put("jobDepth", 0);
                json.put("direction", droneResponse.getOsd().getHeading()/*333.16droneResponse.getOsd().getHeading()*/);
                json.put("speed", droneResponse.getOsd().getGs()/*5droneResponse.getOsd().getGs()*/);
                json.put("altitude", droneResponse.getOsd().getAltitude()/*15.002droneResponse.getOsd().getAltitude()*/);
                jsonArray.put(json);
                System.out.println("request:" + jsonArray);
                String s = HttpUtils.sendHttpPost(url + "/agri-api/job/locationMessage", jsonArray.toString());
                System.out.println("result:" + s);
                ApiUploadResponse apiUploadResponse = new ApiUploadResponse("", s, url + "/agri-api/job/locationMessage", 200);
                return ZhiBaoYunTaskUploader.getRecode(apiUploadResponse, new JSONObject().put("data",jsonArray), "位置信息推送");
                /*return new RecodeTask(null,null,url + "/agri-api/job/locationMessage",jsonArray.toString(),null,s,200,
                        new Date(),"0","0","位置信息推送");*/
            }
        }
        return null;
    }

    /**
     * 轨迹信息推送 有新的架次推送
     *
     * @throws Exception
     */
    public RecodeTask sendTrackMessage(List<JSONObject> osdList, SortieTask sortieTask) {
        JSONObject json = new JSONObject();
        json.put("account", account);
        json.put("password", password);
        json.put("terminalNumber", "612737193106"/*agSortie.getSn()*/);
        JSONArray jsa = new JSONArray();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime startTime = sortieTask.getStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        LocalDateTime endTime = sortieTask.getEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        long totalMillis = Duration.between(startTime, endTime).toMillis();
//        long intervalSeconds = totalSeconds / (osdList.size() - 1); // 计算间隔
        double intervalMillis = (double) totalMillis / (osdList.size() - 1);
        for (int i = 0; i < osdList.size(); i++) {
            org.json.JSONObject osd = osdList.get(i);
            JSONObject jo = new JSONObject();
            // 计算当前时间点
            LocalDateTime currentTime = startTime.plus(Math.round(i * intervalMillis), ChronoUnit.MILLIS);
            // 确保最后一个时间点不超过 endTime
            if (currentTime.isAfter(endTime)) {
                currentTime = endTime;
            }
            jo.put("devicetime", currentTime.format(formatter));
            jo.put("servertime", currentTime.format(formatter));
            jo.put("longitude", osd.get("lon"));
            jo.put("latitude", osd.get("lat"));
            jo.put("altitude", osd.get("alt"));
            double vx = osd.getDouble("vx");
            double vy = osd.getDouble("vy");
            double vz = osd.getDouble("vz");
            double v = UAesUtil.calculateSpeedFromComponents(vx,vy,vz);
            DecimalFormat df = new DecimalFormat("#.##");
            jo.put("speed", df.format(v * 3.6));
            jo.put("direction", osd.get("heading"));
            jo.put("jobDepth", "0");
            jsa.put(jo);
        }
        json.put("positionList", jsa.toString());
        System.out.println("request:" + json);
        String s = null;
        try {
            s = HttpUtils.sendHttpPost(url + "/agri-api/job/traceMessage", json.toString());
            System.out.println("result:" + s);
            ApiUploadResponse apiUploadResponse = new ApiUploadResponse("", s, url + "/agri-api/job/locationMessage", 200);
            return ZhiBaoYunTaskUploader.getRecode(apiUploadResponse, new JSONObject().put("data",jsa), "位置信息推送");
            /*return new RecodeTask(null,null,url + "/agri-api/job/traceMessage",jsa.toString(),null,s,200,
                    new Date(),"0","0","轨迹信息推送");*/
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public List<RecodeTask> putHuBeiTask(TaskDTO taskDTO) {
        List<RecodeTask> recodeTaskList = new ArrayList<>();
        for (SortieTask sortieTask : taskDTO.getSortieTaskList()) {
            RecodeTask recodeArea = sendAreaMessage(sortieTask);
            //发送该架次/作业轨迹
            RecodeTask recodeTrace = putHuBeiTrace(sortieTask);
            ZhiBaoYunTaskUploader.setTaskId(taskDTO, recodeTaskList, recodeArea);
            ZhiBaoYunTaskUploader.setTaskId(taskDTO, recodeTaskList, recodeTrace);
        }
        for (UavTask uavTask : taskDTO.getUavTaskList()) {
            ZhiBaoYunTaskUploader zhiBaoYunTaskUploader = new ZhiBaoYunTaskUploader();
            DroneResponse drone = zhiBaoYunTaskUploader.getDrone(uavTask.getSn(), 1);
            if (drone!=null) {
                RecodeTask recodeLocation = sendLocationMessage(drone);
                ZhiBaoYunTaskUploader.setTaskId(taskDTO, recodeTaskList, recodeLocation);
            }
        }
        return recodeTaskList;
    }

    public RecodeTask putHuBeiTrace(SortieTask sortieTask) {
        if (sortieTask.getPath() != null) {
            List<String> strings = UAesUtil.downloadAndParseFile(sortieTask.getPath());
            if (!strings.isEmpty()) {
                List<JSONObject> traceJson = AESUtil.getJsonObjects(strings);
                return sendTrackMessage(traceJson, sortieTask);
            }
        }
        return null;
    }

    /**
     * 解析GeoJSON并提取coordinates中的经纬度
     * @param geoJson GeoJSON字符串
     * @return 坐标点列表（每个点包含[经度,纬度,高程]）
     */
    public List<double[]> parseGeoJsonCoordinates(String geoJson){
        ObjectMapper mapper = new ObjectMapper();
        JsonNode root = null;
        try {
            root = mapper.readTree(geoJson);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        // 验证是否为FeatureCollection
        if (!"FeatureCollection".equals(root.get("type").asText())) {
            throw new IllegalArgumentException("不是有效的FeatureCollection类型GeoJSON");
        }
        List<double[]> coordinates = new ArrayList<>();
        // 遍历features数组
        JsonNode features = root.get("features");
        if (features.isArray()) {
            for (JsonNode feature : features) {
                if ("land".equals(feature.get("id").asText())) {
                    // 提取coordinates
                    JsonNode coordsNode = feature.get("geometry").get("coordinates");
                    extractCoordinates(coordsNode, coordinates);
                }
            }
        }
        return coordinates;
    }

    /**
     * 递归提取coordinates数据
     */
    private void extractCoordinates(JsonNode coordsNode, List<double[]> result) {
        if (coordsNode.isArray()) {
            // 如果是三维数组（如Polygon）
            if (coordsNode.get(0).get(0).isArray()) {
                for (JsonNode ring : coordsNode) {
                    extractCoordinates(ring, result);
                }
            }
            // 如果是二维数组（如LineString）
            else if (coordsNode.get(0).isArray()) {
                for (JsonNode point : coordsNode) {
                    addCoordinate(point, result);
                }
            }
            // 如果是一维数组（如Point）
            else {
                addCoordinate(coordsNode, result);
            }
        }
    }

    /**
     * 添加单个坐标点到结果集
     */
    private void addCoordinate(JsonNode pointNode, List<double[]> result) {
        double[] point = new double[3];
        point[0] = pointNode.get(0).asDouble(); // 经度
        point[1] = pointNode.get(1).asDouble(); // 纬度
        point[2] = pointNode.size() > 2 ? pointNode.get(2).asDouble() : 0; // 高程（可选）
        result.add(point);
    }

    public static String convertToJsonString(List<double[]> coordinates) {
        StringBuilder sb = new StringBuilder("[");

        for (int i = 0; i < coordinates.size(); i++) {
            double[] point = coordinates.get(i);
            if (point.length < 2) {
                continue; // 跳过无效坐标
            }

            sb.append("{\"lon\":\"")
                    .append(point[0])  // 经度
                    .append("\",\"lat\":\"")
                    .append(point[1])  // 纬度
                    .append("\"}");

            if (i < coordinates.size() - 1) {
                sb.append(","); // 最后一个元素后不加逗号
            }
        }

        sb.append("]");
        return sb.toString();
    }
}
